/*************************************************************************\
*                  Copyright (C) Michael Kerrisk, 2020.                   *
*                                                                         *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the   *
* Free Software Foundation, either version 3 or (at your option) any      *
* later version. This program is distributed without any warranty.  See   *
* the file COPYING.gpl-v3 for details.                                    *
\*************************************************************************/

/* Listing 26-4 */

/* make_zombie.c

   Demonstrate how a child process becomes a zombie in the interval between
   the time it exits, and the time its parent performs a wait (or exits, at
   which time it is adopted by init(8), which does a wait, thus releasing
   the zombie).
*/
#include <signal.h>
#include <libgen.h>             /* For basename() declaration */
#include "tlpi_hdr.h"

#define CMD_SIZE 200

int
main(int argc, char *argv[])
{
	char cmd[CMD_SIZE];
	pid_t childPid;

	setbuf(stdout, NULL);       /* Disable buffering of stdout */

	printf("Parent PID=%ld\n", (long) getpid());

	switch (childPid = fork()) {
	case -1:
		errExit("fork");

	case 0:     /* Child: immediately exits to become zombie */
		printf("Child (PID=%ld) exiting\n", (long) getpid());
		_exit(EXIT_SUCCESS);

	default:    /* Parent */
		sleep(1);               /* Give child a chance to start and exit */
		snprintf(cmd, CMD_SIZE, "ps | grep %s", basename(argv[0]));
		system(cmd);            /* View zombie child */

		/* Now send the "sure kill" signal to the zombie */

		if (kill(childPid, SIGKILL) == -1)
			errMsg("kill");

		sleep(2);               /* Give child a chance to react to signal */
		printf("After sending SIGKILL to zombie (PID=%ld):\n", (long) childPid);
		system(cmd);            /* View zombie child again */

		// Chj: Make a pause here.
		if(argc>1 && argv[1][0]=='0')
		{
			printf("Press Enter to quit, or inspect the zombie child from another terminal.\n");
			getchar();
		}
		
		exit(EXIT_SUCCESS);
	}
}
